﻿using log4net;
using SimpleCrawler.DAL;
using SimpleCrawler.DependencyInjection;
using SimpleCrawler.Entity;
using SimpleCrawler.Logger;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace SimpleCrawler.Crawler
{
    public class CrawlerAction
    {
        //日志 记录爬虫状态
        private ILog logger;
        private CrawlerBase WebCrawler;
        private string CrawlerType;
        public CrawlerAction(CrawlerBase crawler) {
            WebCrawler = crawler;
            CrawlerType = crawler.TypeName.Name;
            logger = LoggerManager.GetLogger(crawler.TypeName); 
        }

        private int pagemins = 3*60*1000;
        private int taskmins = 10* 60*1000;
        private int blackListmins = 30 * 60 * 1000;

        /// <summary>
        /// 当前线程爬虫类别ID
        /// </summary>
        public int CrawlerID{get{ return WebCrawler.CrawlerID; } }

        /// <summary>
        /// 分配给爬虫任务
        /// </summary>
        public List<CrawlerTask> TaskList { get; set; } = new List<CrawlerTask>();

        /// <summary>
        /// 根据任务和是否需要分页抓取网页
        /// 此方法监控爬虫状态是否正常,此时可能已经进入黑名单 1.页面返回状态非200 2.服务器返回空内容 3.返回内容完全无法匹配记录 
        /// 页面返回正常 代码处理错误(正则匹配 cookie处理)时请在爬虫实现类中控制  参考QiHu360WenDaCrawler  
        /// 分页逻辑根据返回页处理时 在GetResultContent中控制endpage
        /// </summary>
        public async void Start()
        {
            if (TaskList.Count > 0)
            {
                try
                {
                    var watch = new Stopwatch();
                    for (int i = 0; i < TaskList.Count;i++)
                    {
                        int sumRecord = 0;//成功抓取条数  如果抓取成功过后出现异常 则可能进入黑名单 如果一次都没成功 则爬虫实现类有问题
                        CrawlerTask task = TaskList[i];
                        task.TaskName = string.IsNullOrEmpty(task.KeyWord) ? task.TaskName : task.TaskName + "--" + task.KeyWord;
                        string taskname = task.TaskName;
                        WebCrawler.CrawlerTask = task;
                        WebCrawler.GetStartedPageUrl();
                        restart: watch.Restart();
                        try
                        {
                            if (task.NeedNext)
                                taskname = task.TaskName + $"(分页{task.StartPage})";

                            Console.WriteLine($"----------------------开始任务:{CrawlerType + "--" + taskname}----------------------------");
                            string html = await WebCrawler.GetTargetHtmlString();
                            if (!string.IsNullOrWhiteSpace(html))
                            {
                                int count = await WebCrawler.GetResultContent(html);
                                watch.Stop();
                                if (count == 0)
                                {
                                    if (sumRecord > 0)
                                    {
                                        Console.WriteLine($"---------------暂停任务{CrawlerType + "--" + taskname}:已进入黑名单---------------");
                                        logger.Warn($"已进入黑名单,暂停任务:{CrawlerType + "--" + taskname}:已采集{sumRecord}条记录,当前页码:{task.StartPage}");
                                        sumRecord = 0;
                                        Thread.Sleep(blackListmins);
                                        goto restart;
                                    }
                                    else if (sumRecord == 0)
                                    {
                                        Console.WriteLine($"---------------结束任务{CrawlerType + "--" + taskname}:没有匹配的数据---------------");
                                        logger.Error($"结束任务{CrawlerType + "--" + taskname}:没有匹配的数据,当前页面:{task.StartPage}");
                                        break;
                                    }
                                }
                                var milliseconds = watch.ElapsedMilliseconds;
                                count = count < 0 ? 0 : count;//count为负数表示此页不需要抓取
                                sumRecord += count;
                                Console.WriteLine($"----------------------{CrawlerType + "--" + taskname},已采集{count}条数据,用时:{milliseconds}----------------------------");
                                if (task.NeedNext && task.StartPage < task.EndPage)
                                {
                                    Thread.Sleep(pagemins);
                                    WebCrawler.GetNextPageUrl(++task.StartPage);
                                    goto restart;
                                }
                            }
                            else if(sumRecord>0)
                            {
                                Console.WriteLine($"---------------暂停任务{CrawlerType + "--" + taskname}:已进入黑名单---------------");
                                logger.Warn($"已进入黑名单,暂停任务:{CrawlerType + "--" + taskname}:已采集{sumRecord}条记录,当前页码:{task.StartPage}");
                                sumRecord = 0;
                                Thread.Sleep(blackListmins);
                                goto restart;
                            }
                            else
                            {
                                Console.WriteLine($"---------------结束任务{CrawlerType + "--" + taskname}:目标地址html获取失败---------------");
                                logger.Error($"结束任务{CrawlerType + "--" + taskname}:目标地址html获取失败,当前页面:{task.StartPage}");
                                break;
                            }
                        }
                        catch (Exception ex) {
                            if (sumRecord > 0)
                            {
                                Console.WriteLine($"---------------暂停任务{CrawlerType + "--" + taskname}:已进入黑名单---------------");
                                logger.Warn($"已进入黑名单,暂停任务:{CrawlerType + "--" + taskname}:已采集{sumRecord}条记录,当前页码:{task.StartPage}");
                                sumRecord = 0;
                                Thread.Sleep(blackListmins);
                                goto restart;
                            }
                            else if (sumRecord == 0)
                            {
                                Console.WriteLine($"---------------结束任务{CrawlerType + "--" + task.TaskName}:异常结束任务---------------");
                                Console.WriteLine(ex.ToString());
                                logger.Error($"结束任务{CrawlerType + "--" + taskname}:异常结束任务,当前页面:{task.StartPage}     " + ex.ToString());
                                break;
                            }
                        }
                        Console.WriteLine($"----------任务完成:{CrawlerType + "--" + task.TaskName}:已采集{sumRecord}条记录,当前页码:{task.StartPage}----------");
                        logger.Warn($"任务完成:{CrawlerType + "--" + task.TaskName}:已采集{sumRecord}条记录,当前页码:{task.StartPage}");
                        Thread.Sleep(taskmins);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"{CrawlerType} 异常结束任务" + ex.ToString());
                    logger.Error(ex.ToString());
                }
            }
        }
    }
}
